#include "AnimationManager.h"
#include "AnimationInfo.h"
#include "Animation.h"
#include "Frame.h"
#include "../tinyxml/tinyxml.h"
#include <string>
#include <Windows.h>
#include <sstream>

#include <cassert>

CAnimationManager::CAnimationManager(void)
{
	m_pTM	= CSGD_TextureManager::GetInstance();
	//m_unRefCount = 0;

	
}
CAnimationManager* CAnimationManager::GetInstance()
{
	// Static local variable:
	static CAnimationManager s_Instance;

	// Return the address
	return &s_Instance;
}
CAnimationManager::~CAnimationManager(void)
{
	
}
bool CAnimationManager::Load( const char* _szFilename )
{
	// create a new animation
	// create frames
	// put into list
	//**********************************************
	//*******************************************************************************	
	TiXmlDocument doc;

	if( doc.LoadFile(_szFilename) == false )
		return false;

	TiXmlElement* pRoot = doc.RootElement();

	if( pRoot == nullptr )
		return false;
	// Animation is the First Child of ROOT
	TiXmlElement* pAnimation = pRoot->FirstChildElement( "Animation" );

	while( pAnimation != nullptr )
	{
		// ANIMATION NAME
		m_pXMLanimation = new CAnimation();
		const char* pText = pAnimation->Attribute("Name");
			if( pText != nullptr )
				m_pXMLanimation->SetName( pText );

		// LOOPING
		double tempbool;
		pAnimation->Attribute( "IsLooping", &tempbool );
		if( tempbool == 1 )
			m_pXMLanimation->SetIsLooping( true );
		else if( tempbool == 0 )
			m_pXMLanimation->SetIsLooping( false );

		// ANIMATION IMAGE ID
		ostringstream output;
		output << "resources/graphics/" << m_pXMLanimation->m_szName.c_str() << ".png";
		m_pXMLanimation->m_nImageID = m_pTM->LoadTexture( output.str().c_str() );


		// Frame is the First Child of ANIMATION
		TiXmlElement* pFrame = pAnimation->FirstChildElement("Frame");
		while( pFrame != nullptr)
		{
			tempFrame = new CFrame();
			double temp;
			// ANCHOR POINT
			pFrame->Attribute( "AnchorPointX", &temp);
			tempFrame->m_AnchorPoint.x = (LONG)temp;
			pFrame->Attribute( "AnchorPointY", &temp);
			tempFrame->m_AnchorPoint.y = (LONG)temp;
			// COLLISION RECT
			pFrame->Attribute( "CollisionLeft", &temp);
			tempFrame->m_CollisionRect.left = (LONG)temp;
			pFrame->Attribute( "CollisionTop", &temp);
			tempFrame->m_CollisionRect.top = (LONG)temp;
			pFrame->Attribute( "CollisionRight", &temp);
			tempFrame->m_CollisionRect.right = (LONG)temp;
			pFrame->Attribute( "CollisionBottom", &temp);
			tempFrame->m_CollisionRect.bottom = (LONG)temp;
			// DRAW RECT
			pFrame->Attribute( "DrawLeft", &temp);
			tempFrame->m_DrawRect.left = (LONG)temp;
			pFrame->Attribute( "DrawTop", &temp);
			tempFrame->m_DrawRect.top = (LONG)temp;
			pFrame->Attribute( "DrawRight", &temp);
			tempFrame->m_DrawRect.right = (LONG)temp;
			pFrame->Attribute( "DrawBottom", &temp);
			tempFrame->m_DrawRect.bottom = (LONG)temp;
			// MESSAGE SYSTEM
			const char* pMessage = pFrame->Attribute("Message");
			if( pMessage != nullptr )
				tempFrame->SetMessage( pMessage );
			// TIME
			pFrame->Attribute( "Time", &temp);
			tempFrame->m_fTime = (LONG)temp;
			// COLLISION INFO
			pFrame->Attribute( "CollisionInfo", &temp);
			tempFrame->m_nCollisionInfo = (LONG)temp;

			// Push back current frame into Curent Animation
			m_pXMLanimation->m_vFrames.push_back( tempFrame );
			// Move the current node to the Next sibling
			pFrame = pFrame->NextSiblingElement("Frame");
		}
		// Insert Current Animation into Animations MAP
		m_mLoadedAnimations.insert( std::pair< string, CAnimation*>( m_pXMLanimation->m_szName, m_pXMLanimation ) );	
		// MOVE Current node to next sibling
		pAnimation = pAnimation->NextSiblingElement( "Animation" );
	}

	return true;


//**********************************************************************
	/*
	doc.LinkEndChild( pDec );
	TiXmlElement* pRoot = new TiXmlElement("Animations");
	std::map< string, CAnimation* >::const_iterator iter;
	for( iter = m_mLoadedAnimations.begin(); iter != m_mLoadedAnimations.end(); ++iter )
	{

		TiXmlElement* pAnimation = new TiXmlElement( "Animations" );	
		m_pXMLanimation = new CAnimation();
		pAnimation->SetAttribute( "ImageID", (*iter).second->GetImageID() );
		// Might need to save Looping accessor to temporary INT variable
		pAnimation->SetAttribute( "Looping", (*iter).second->GetIsLooping() );
		pAnimation->SetAttribute( "Name", (*iter).second->GetName().c_str() );


		//pAnimation->SetAttribute( "scale", (*iter).second->m_vFrames[pAnimation]->m_fScale );
	}
	*/
	

	//**********************************************

	/*

	load( filename)
	io setup
	for( animation != end)
	{
		new animation;
			for( frame != end)
			{
				new frame;
				load attributes;
				Animation.frame.pushback(frame)
			}
			map.insert(animation)

	}
	*/







	/*
	// TEMPORARY CODE *****************************
	frame11 = new CFrame();
	frame12 = new CFrame();
	frame13 = new CFrame();
	frame14 = new CFrame();
	Animation1 = new CAnimation();
	frame21 = new CFrame();
	frame22 = new CFrame();
	frame23 = new CFrame();
	Animation2 = new CAnimation();

	frame11->m_fScale = 1.0f;
	frame11->m_AnchorPoint.x = 7;
	frame11->m_AnchorPoint.y = 39;
	frame11->m_CollisionRect.left = 13;
	frame11->m_CollisionRect.top = 2;
	frame11->m_CollisionRect.right = 29;
	frame11->m_CollisionRect.bottom = 40;
	frame11->m_DrawRect.left = 13;
	frame11->m_DrawRect.top = 2;
	frame11->m_DrawRect.right = 29;
	frame11->m_DrawRect.bottom = 40;
	frame11->m_fRotation = 0.0f;
	frame11->m_fTime = 1.0f;
	Animation1->m_vFrames.push_back( frame11 );

	frame12->m_fScale = 1.0f;
	frame12->m_AnchorPoint.x = 12;
	frame12->m_AnchorPoint.y = 39;
	frame12->m_CollisionRect.left = 48;
	frame12->m_CollisionRect.top = 1;
	frame12->m_CollisionRect.right = 70;
	frame12->m_CollisionRect.bottom = 39;
	frame12->m_DrawRect.left = 48;
	frame12->m_DrawRect.top = 1;
	frame12->m_DrawRect.right = 70;
	frame12->m_DrawRect.bottom = 39;
	frame12->m_fRotation = 0.0f;
	frame12->m_fTime = 1.0f;
	Animation1->m_vFrames.push_back( frame12 );

	frame13->m_fScale = 1.0f;
	frame13->m_AnchorPoint.x = 9;
	frame13->m_AnchorPoint.y = 40;
	frame13->m_CollisionRect.left = 88;
	frame13->m_CollisionRect.top = 1;
	frame13->m_CollisionRect.right = 103;
	frame13->m_CollisionRect.bottom = 38;
	frame13->m_DrawRect.left = 88;
	frame13->m_DrawRect.top = 1;
	frame13->m_DrawRect.right = 103;
	frame13->m_DrawRect.bottom = 38;
	frame13->m_fRotation = 0.0f;
	frame13->m_fTime = 1.0f;
	Animation1->m_vFrames.push_back( frame13 );
	
	frame14->m_fScale = 1.0f;
	frame14->m_AnchorPoint.x = 11;
	frame14->m_AnchorPoint.y = 37;
	frame14->m_CollisionRect.left = 124;
	frame14->m_CollisionRect.top = 2;
	frame14->m_CollisionRect.right = 146;
	frame14->m_CollisionRect.bottom = 37;
	frame14->m_DrawRect.left = 124;
	frame14->m_DrawRect.top = 2;
	frame14->m_DrawRect.right = 146;
	frame14->m_DrawRect.bottom = 37;
	frame14->m_fRotation = 0.0f;
	frame14->m_fTime = 1.0f;
	Animation1->m_vFrames.push_back( frame14 );

	Animation1->SetIsLooping( true );
	Animation1->m_nImageID = m_pTM->LoadTexture( _T("resources/graphics/PC_PlayerWalkLeft.png") );
	string name = "example";

	m_mLoadedAnimations.insert( std::pair< string, CAnimation*>( name, Animation1 ) );

	frame21->m_fScale = 1.0f;
	frame21->m_AnchorPoint.x = 14;
	frame21->m_AnchorPoint.y = 49;
	frame21->m_CollisionRect.left = 0;
	frame21->m_CollisionRect.top = 0;
	frame21->m_CollisionRect.right = 29;
	frame21->m_CollisionRect.bottom = 47;
	frame21->m_DrawRect.left = 0;
	frame21->m_DrawRect.top = 0;
	frame21->m_DrawRect.right = 29;
	frame21->m_DrawRect.bottom = 47;
	frame21->m_fRotation = 0.0f;
	frame21->m_fTime = 5.0f;
	Animation2->m_vFrames.push_back( frame21 );

	frame22->m_fScale = 1.0f;
	frame22->m_AnchorPoint.x = 14;
	frame22->m_AnchorPoint.y = 49;
	frame22->m_CollisionRect.left = 0;
	frame22->m_CollisionRect.top = 50;
	frame22->m_CollisionRect.right = 29;
	frame22->m_CollisionRect.bottom = 99;
	frame22->m_DrawRect.left = 0;
	frame22->m_DrawRect.top = 50;
	frame22->m_DrawRect.right = 29;
	frame22->m_DrawRect.bottom = 99;
	frame22->m_fRotation = 0.0f;
	frame22->m_fTime = 5.0f;
	Animation2->m_vFrames.push_back( frame22 );

	frame23->m_fScale = 1.0f;
	frame23->m_AnchorPoint.x = 14;
	frame23->m_AnchorPoint.y = 49;
	frame23->m_CollisionRect.left = 1;
	frame23->m_CollisionRect.top = 100;
	frame23->m_CollisionRect.right = 28;
	frame23->m_CollisionRect.bottom = 148;
	frame23->m_DrawRect.left = 1;
	frame23->m_DrawRect.top = 100;
	frame23->m_DrawRect.right = 28;
	frame23->m_DrawRect.bottom = 148;
	frame23->m_fRotation = 0.0f;
	frame23->m_fTime = 5.0f;
	Animation2->m_vFrames.push_back( frame23 );
	
	Animation2->SetIsLooping( true );
	Animation2->m_nImageID = m_pTM->LoadTexture( _T("resources/graphics/zombie.png") );
	string zombie = "zombie";

	m_mLoadedAnimations.insert( std::pair< string, CAnimation*>( zombie, Animation2 ) );
	*/

}
void CAnimationManager::Update( CAnimationInfo* _cCurrAnimation, float _fElapsedTime )
{

	/*
		create animation & frame* in animinfo
		when i switch the current animation i need to update the pointers, as well as when i update frames
	*/


		//m_pFrame.SetMessage( m_mLoadedAnimations[ _cCurrAnimation->GetCurrentAnimation() ]->m_vFrames[ _cCurrAnimation->GetCurrentFrame() ]->GetMessageA() );


	

	// Increase our timer
	_cCurrAnimation->SetTimeWaited( _cCurrAnimation->GetTimeWaited() + _fElapsedTime );
	
	// Move to the next frame?
	if(  _cCurrAnimation->GetTimeWaited() >= m_mLoadedAnimations[ _cCurrAnimation->GetCurrentAnimation() ]->m_vFrames[ _cCurrAnimation->GetCurrentFrame() ]->GetTimePerFrame() )
	{
		_cCurrAnimation->SetTimeWaited( 0.0f );
		_cCurrAnimation->SetCurrentFrame( _cCurrAnimation->GetCurrentFrame()+1 );


		// Have we reached the end?
		if( _cCurrAnimation->GetCurrentFrame() >= m_mLoadedAnimations[ _cCurrAnimation->GetCurrentAnimation() ]->m_vFrames.size() )
		{
			// Loop?
			if( m_mLoadedAnimations[ _cCurrAnimation->GetCurrentAnimation() ]->GetIsLooping() )
			{
				 _cCurrAnimation->SetCurrentFrame( 0 );
			}
			else
			{
				 _cCurrAnimation->SetCurrentFrame( m_mLoadedAnimations[ _cCurrAnimation->GetCurrentAnimation() ]->m_vFrames.size() -1 );				
			}
	   }
	}
		m_pFrame.SetMessage( m_mLoadedAnimations[ _cCurrAnimation->GetCurrentAnimation() ]->m_vFrames[ _cCurrAnimation->GetCurrentFrame() ]->GetMessageA() );

}
void CAnimationManager::Render( CAnimationInfo* _cCurrAnimation, int _nPosX, int _nPosY, 
			bool bIsFlipped, DWORD dwColor )
{
	// Get source rect and anchor from the current frame
	RECT rFrame = m_mLoadedAnimations[ _cCurrAnimation->GetCurrentAnimation() ]->m_vFrames[ _cCurrAnimation->GetCurrentFrame() ]->GetDrawRect();	
	POINT ptAnchor = m_mLoadedAnimations[ _cCurrAnimation->GetCurrentAnimation() ]->m_vFrames[ _cCurrAnimation->GetCurrentFrame() ]->GetAnchorPoint();
	float fScale = m_mLoadedAnimations[ _cCurrAnimation->GetCurrentAnimation() ]->m_vFrames[ _cCurrAnimation->GetCurrentFrame() ]->m_fScale;
  

  if( bIsFlipped )
   fScale = -fScale;

  // Offset the position by the anchor point
  m_pTM->Draw( m_mLoadedAnimations[ _cCurrAnimation->GetCurrentAnimation() ]->GetImageID(),
				_nPosX - (ptAnchor.x * fScale), 
					_nPosY - (ptAnchor.y * fScale), 
						 fScale, 
							fScale, 
								&rFrame,
									0.0f, 
										0.0f, 
											0.0f, 
												dwColor );

  

}
void CAnimationManager::Shutdown(void)
{
	
	delete Animation;
	delete m_pXMLanimation;
	delete tempFrame;

}
/*
void CAnimationManager::AddRef( void )
{
	// Increase the reference 
	m_unRefCount++;

}
void CAnimationManager::Release( void )
{
	// Decrease the reference count (-1 friend :(  ... )
	m_unRefCount--;

	// Self-destruct when the count reaches 0
	if( m_unRefCount == 0 )
		delete this;

}
*/